package com.castlzl.random.config;

import com.castlzl.random.core.IdGenerator;
import com.castlzl.random.core.guid.GuidGenerator;
import com.castlzl.random.core.leaf.LeafSegmentService;
import com.castlzl.random.core.leaf.zookeeper.ZookeeperSegmentServiceImpl;
import com.castlzl.random.core.snowflake.SnowflakeIdGenerator;
import com.castlzl.random.core.tinyid.TinyIdSegmentService;
import com.castlzl.random.core.tinyid.redis.RedisTinyIdSegmentServiceImpl;
import com.castlzl.random.core.tinyid.zookeeper.ZookeeperTinyIdSegmentServiceImpl;
import com.castlzl.random.core.uid.UidGenerator;
import com.castlzl.random.core.leaf.LeafSegmentIdGenerator;
import com.castlzl.random.core.leaf.redis.RedisLeafSegmentServiceImpl;
import com.castlzl.random.core.tinyid.TinyIdGenerator;
import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.CuratorFramework;

import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;

/**
 * @author leiziliang
 */
@Slf4j
@Configuration
@ConditionalOnClass(IdGenerator.class)
public class RandomIdAutoConfiguration {

    /**
     * 配置RandomId属性 bean
     *
     * 该方法通过Spring的@Bean注解定义了一个bean，使得RandomIdProperties类的实例可以被Spring容器管理和注入
     * 使用@ConfigurationProperties注解将该bean与配置文件中以'random-id'为前缀的属性进行绑定，实现自动配置
     *
     * @return RandomIdProperties实例，包含从配置文件中读取的属性值
     */
    @Bean
    @ConfigurationProperties(prefix = "random-id")
    public RandomIdProperties randomIdProperties() {
        log.warn("加载了：randomIdProperties");
        return new RandomIdProperties();
    }

    @Bean
    @ConditionalOnProperty(prefix = "random-id", name = "type", havingValue = "snowflake", matchIfMissing = true)
    @ConditionalOnMissingBean
    public IdGenerator snowflakeIdGenerator(RandomIdProperties properties) {
        return new SnowflakeIdGenerator(properties.getWorkerId(), properties.getDatacenterId());
    }

    

    @Bean
    @ConditionalOnProperty(prefix = "random-id", name = "segment-storage-type", havingValue = "redis")
    @ConditionalOnClass(StringRedisTemplate.class)
    @ConditionalOnMissingBean
    public LeafSegmentService redisSegmentService(StringRedisTemplate redisTemplate, RandomIdProperties properties) {
        return new RedisLeafSegmentServiceImpl(redisTemplate, properties.getStep(), properties.getKeyPrefix());
    }

    @Bean
    @ConditionalOnProperty(prefix = "random-id", name = "type", havingValue = "leaf")
    @ConditionalOnMissingBean
    public IdGenerator leafSegmentIdGenerator(LeafSegmentService leafSegmentService, RandomIdProperties properties) {
        return new LeafSegmentIdGenerator(properties.getBizTag(), leafSegmentService, properties.isAsyncLoadingSegment());
    }


    @Bean
    @ConditionalOnProperty(prefix = "random-id", name = "segment-storage-type", havingValue = "zookeeper")
    @ConditionalOnClass(CuratorFramework.class)
    @ConditionalOnMissingBean
    public LeafSegmentService zookeeperSegmentService(CuratorFramework client, RandomIdProperties properties) {
        return new ZookeeperSegmentServiceImpl(client, properties.getStep(), properties.getPathPrefix());
    }

    @Bean
    @ConditionalOnProperty(prefix = "random-id", name = "type", havingValue = "uid")
    @ConditionalOnMissingBean
    public IdGenerator uidGenerator(RandomIdProperties properties) {
        return new UidGenerator(properties.getWorkerId());
    }

    @Bean
    @ConditionalOnProperty(prefix = "random-id", name = "type", havingValue = "tiny")
    @ConditionalOnMissingBean
    public IdGenerator tinyIdGenerator(TinyIdSegmentService tinyIdSegmentService, RandomIdProperties properties) {
        log.warn("加载了：tinyIdSegmentService");
        return new TinyIdGenerator(properties.getBizTag(), tinyIdSegmentService, properties.isAsyncLoadingSegment());
    }

    @Bean
    //@ConditionalOnProperty(prefix = "random-id", name = {"segment-storage-type", "type"}, havingValue = "redis")
    @ConditionalOnExpression("'${random-id.segment-storage-type}' == 'redis' && '${random-id.type}' == 'tiny'")
    @ConditionalOnClass(StringRedisTemplate.class)
    @ConditionalOnMissingBean
    public TinyIdSegmentService redisTinyIdSegmentService(StringRedisTemplate redisTemplate, RandomIdProperties properties) {
        return new RedisTinyIdSegmentServiceImpl(redisTemplate, properties.getStep(), properties.getKeyPrefix());
    }

    @Bean
//    @ConditionalOnProperty(prefix = "random-id", name = {"segment-storage-type", "type"}, havingValue = "zookeeper")
    @ConditionalOnExpression("'${random-id.segment-storage-type}' == 'zookeeper' && '${random-id.type}' == 'tiny'")
    @ConditionalOnClass(CuratorFramework.class)
    @ConditionalOnMissingBean
    public TinyIdSegmentService zookeeperTinyIdSegmentService(CuratorFramework client, RandomIdProperties properties) {
        return new ZookeeperTinyIdSegmentServiceImpl(client, properties.getStep(), properties.getPathPrefix());
    }

    @Bean
    @ConditionalOnProperty(prefix = "random-id", name = "type", havingValue = "guid")
    @ConditionalOnMissingBean
    public IdGenerator guidGenerator() {
        return new GuidGenerator();
    }
}